前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# 网络服务 https

30 秒速记

  • HTTPS = HTTP 跑在 TLS 上:内容加密 + 验证对方身份
  • 客户端验证证书看三件事:信任链能追到受信任的 CA、没过期、域名和证书的 SAN 对得上
  • 自签名、内网 CA 证书的正确姿势是通过 ca 选项或 NODE_EXTRA_CA_CERTS 加信任,不是关校验
  • rejectUnauthorized: false / NODE_TLS_REJECT_UNAUTHORIZED=0 等于没有身份验证,只能临时排查用
  • 私钥不进仓库、不进镜像层,走密钥管理;线上常在 Nginx 或网关终止 TLS

Node 的 https 模块就是在 http 外面套了一层 TLS,用法几乎一样,多出来的全是证书相关的事。 TLS 干两件事:一是把内容加密,二是让客户端确认「对面真的是这个网站」,后者靠证书。所以 HTTPS 出问题,十有八九是证书问题:证书链不全、过期、域名对不上、用了自签名。碰到证书报错,正确做法是把对应的 CA 加进信任列表,而不是把校验关掉,关掉就等于谁都能冒充服务端。

理解「网络服务 https」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 network 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

HTTPS 客户端和服务端在 Node 里的写法跟 http 基本是一一对应的,差别都在证书相关的选项上。

const https = require('https')
const fs = require('fs')

// 服务端:比 http.createServer 多一个 { key, cert }
https
  .createServer(
    { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') },
    (req, res) => res.end('hello https'),
  )
  .listen(8443)

// 客户端:请求自签名证书的服务
https.get(
  'https://localhost:8443',
  { ca: fs.readFileSync('cert.pem') }, // 把这张证书当成受信任的 CA,校验照常进行
  (res) => res.pipe(process.stdout), // 输出 hello https
).on('error', (e) => console.error(e.code)) // 不传 ca 时输出 DEPTH_ZERO_SELF_SIGNED_CERT
@前端进阶之旅: 代码已经复制到剪贴板

不传 ca 时,客户端会报 DEPTH_ZERO_SELF_SIGNED_CERT,这正是证书校验在起作用。很多教程教的 rejectUnauthorized: false 能让请求通过,但它把「验证对方是谁」整个关掉了,只适合在本机临时确认是不是证书问题。

常见报错和对应原因可以记一下:DEPTH_ZERO_SELF_SIGNED_CERT / SELF_SIGNED_CERT_IN_CHAIN 是自签名或私有 CA,加信任;UNABLE_TO_VERIFY_LEAF_SIGNATURE 一般是服务端没发中间证书;CERT_HAS_EXPIRED 是过期;ERR_TLS_CERT_ALTNAME_INVALID 是访问的域名不在证书的 SAN 列表里。

面试官追问

追问 1Node 请求内网服务报 self signed certificate,同事加了 NODE_TLS_REJECT_UNAUTHORIZED=0 就好了,能这么上线吗?
参考回答

我会直接拦。这个环境变量会让整个进程所有 HTTPS 请求都不验证证书,中间人可以随便冒充。正确做法是拿到内网 CA 证书,启动时设 NODE_EXTRA_CA_CERTS=/path/ca.pem,或者在请求里传 ca 选项。

追问 2浏览器能打开的网站,Node 请求却报 unable to verify the first certificate,为什么?
参考回答

多半是服务端没把中间证书发全。浏览器会自动补全或者有缓存,Node 不会。用 openssl s_client -connect host:443 -showcerts 看一下发回来的证书链,让服务端配上完整链才是根治。

追问 3证书过期导致线上请求全挂,怎么提前发现?
参考回答

定时脚本读证书的到期时间,比如 tls.connect 之后 socket.getPeerCertificate().valid_to,剩 30 天就告警。证书用 Let's Encrypt 这类自动续期的话,也要监控续期任务有没有真的跑成功。

追问 4Node 服务要自己开 HTTPS,还是交给前面的 Nginx?
参考回答

一般交给 Nginx 或网关,证书集中管、续期方便,Node 只跑 HTTP。只有内网也要求加密、或者没有反向代理的时候,才让 Node 自己加载证书。

# 模块概览

30 秒速记

  • https 模块 API 和 http 几乎一一对应:https.get / https.request / https.createServer
  • 多出来的是 TLS 选项:服务端要 key、cert,客户端可以传 ca、rejectUnauthorized、servername
  • 浏览器和 Node 的信任库不一样:Node 用自带的 CA 列表,不读系统证书(Node 23.8 起才可以用 --use-system-ca)
  • 访问证书不受信任的站点,正确做法是加 ca,rejectUnauthorized: false 只能临时排查

https 模块的用法跟 http 几乎一样,把模块名和协议换掉就能跑,真正要多学的是证书。 服务端启动时要提供私钥和证书;客户端默认会严格校验对方证书,校验不过直接报错。早年 12306 用的是自己签的证书,浏览器要手动装根证书,Node 去请求也会报错,就是这个原因。还有一点容易忽略:Node 不用操作系统的证书库,公司内网 CA 装到系统里了,浏览器能打开,Node 照样报错。

这个模块的重要性,基本不用强调了。在网络安全问题日益严峻的今天,网站采用HTTPS是个必然的趋势。

在nodejs中,提供了 https 这个模块来完成 HTTPS 相关功能。从官方文档来看,跟 http 模块用法非常相似。

本文主要包含两部分:

  1. 通过客户端、服务端的例子,对https模块进行入门讲解。
  2. 如何访问安全证书不受信任的网站。(以 12306 为例子)

篇幅所限,本文无法对 HTTPS协议 及 相关技术体系 做过多讲解,有问题欢迎留言交流。

面试官追问

追问 1把 require('http') 换成 require('https'),服务就能上线了吗?
参考回答

不能。服务端 createServer 第一个参数要传 { key, cert },没有证书根本起不来。客户端那边,对方证书有问题也会直接报错,得先把证书链路理顺。

追问 2公司内网 CA 已经装进系统了,浏览器能打开,Node 还是报证书错误,为什么?
参考回答

Node 默认用自己打包的 CA 列表,不读系统证书库。启动时加 NODE_EXTRA_CA_CERTS=/path/company-ca.pem 就行,新版本也可以用 --use-system-ca。

追问 3联调时测试环境证书不受信任,想临时绕过,怎么做才不出事?
参考回答

只在这一个请求上传 ca 指向测试环境的证书,校验照常进行。实在要用 rejectUnauthorized: false,也只写在测试代码里,别用全局环境变量,更别带进生产配置。

追问 4一台服务器上挂了多个域名的 HTTPS 服务,客户端拿到的证书不对,可能是什么?
参考回答

SNI 没传对。Node 客户端默认用 hostname 当 servername,如果是用 IP 直连再手动加 Host 头,就要显式传 servername: 'api.example.com',服务端才知道该返回哪张证书。

# 客户端例子

30 秒速记

  • https.get(url, cb) 和 http.get 写法一样,回调拿到的 res 也是流
  • res.on('data') 里拿到的是一块块数据,要完整内容就拼起来等 end
  • .on('error') 管的是请求侧失败:DNS、连接、证书校验;正文读到一半断开要看 res 的 close / aborted
  • 证书错误会走这里的 error,比如 CERT_HAS_EXPIRED,不监听进程直接崩
  • 要设方法、请求头或写正文,就换 https.request

https.get() 跟 http.get() 的用法完全一样,只是请求地址换成了 https。 回调触发时只有状态码和响应头到了,正文通过 data 一块块来,示例里直接 process.stdout.write 边收边打。.on('error') 一定要写,HTTPS 比 HTTP 多了一类错误就是证书校验失败,过期、域名不匹配、自签名都会从这里抛出来。要自定义方法、请求头或者带正文,就换 https.request(options, cb),最后记得 end()。

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
      • 模块概览
      • 客户端例子
      • 服务端例子
        • 生成证书
        • HTTPS服务端
      • 进阶例子:访问安全证书不受信任的网站
      • 相关链接
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

网络服务 https|Nodejs专题系列

# 网络服务 https

30 秒速记

  • HTTPS = HTTP 跑在 TLS 上:内容加密 + 验证对方身份
  • 客户端验证证书看三件事:信任链能追到受信任的 CA、没过期、域名和证书的 SAN 对得上
  • 自签名、内网 CA 证书的正确姿势是通过 ca 选项或 NODE_EXTRA_CA_CERTS 加信任,不是关校验
  • rejectUnauthorized: false / NODE_TLS_REJECT_UNAUTHORIZED=0 等于没有身份验证,只能临时排查用
  • 私钥不进仓库、不进镜像层,走密钥管理;线上常在 Nginx 或网关终止 TLS

Node 的 https 模块就是在 http 外面套了一层 TLS,用法几乎一样,多出来的全是证书相关的事。 TLS 干两件事:一是把内容加密,二是让客户端确认「对面真的是这个网站」,后者靠证书。所以 HTTPS 出问题,十有八九是证书问题:证书链不全、过期、域名对不上、用了自签名。碰到证书报错,正确做法是把对应的 CA 加进信任列表,而不是把校验关掉,关掉就等于谁都能冒充服务端。

理解「网络服务 https」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 network 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

HTTPS 客户端和服务端在 Node 里的写法跟 http 基本是一一对应的,差别都在证书相关的选项上。

const https = require('https')
const fs = require('fs')

// 服务端:比 http.createServer 多一个 { key, cert }
https
  .createServer(
    { key: fs.readFileSync('key.pem'), cert: fs.readFileSync('cert.pem') },
    (req, res) => res.end('hello https'),
  )
  .listen(8443)

// 客户端:请求自签名证书的服务
https.get(
  'https://localhost:8443',
  { ca: fs.readFileSync('cert.pem') }, // 把这张证书当成受信任的 CA,校验照常进行
  (res) => res.pipe(process.stdout), // 输出 hello https
).on('error', (e) => console.error(e.code)) // 不传 ca 时输出 DEPTH_ZERO_SELF_SIGNED_CERT
@前端进阶之旅: 代码已经复制到剪贴板

不传 ca 时,客户端会报 DEPTH_ZERO_SELF_SIGNED_CERT,这正是证书校验在起作用。很多教程教的 rejectUnauthorized: false 能让请求通过,但它把「验证对方是谁」整个关掉了,只适合在本机临时确认是不是证书问题。

常见报错和对应原因可以记一下:DEPTH_ZERO_SELF_SIGNED_CERT / SELF_SIGNED_CERT_IN_CHAIN 是自签名或私有 CA,加信任;UNABLE_TO_VERIFY_LEAF_SIGNATURE 一般是服务端没发中间证书;CERT_HAS_EXPIRED 是过期;ERR_TLS_CERT_ALTNAME_INVALID 是访问的域名不在证书的 SAN 列表里。

面试官追问

追问 1Node 请求内网服务报 self signed certificate,同事加了 NODE_TLS_REJECT_UNAUTHORIZED=0 就好了,能这么上线吗?
参考回答

我会直接拦。这个环境变量会让整个进程所有 HTTPS 请求都不验证证书,中间人可以随便冒充。正确做法是拿到内网 CA 证书,启动时设 NODE_EXTRA_CA_CERTS=/path/ca.pem,或者在请求里传 ca 选项。

追问 2浏览器能打开的网站,Node 请求却报 unable to verify the first certificate,为什么?
参考回答

多半是服务端没把中间证书发全。浏览器会自动补全或者有缓存,Node 不会。用 openssl s_client -connect host:443 -showcerts 看一下发回来的证书链,让服务端配上完整链才是根治。

追问 3证书过期导致线上请求全挂,怎么提前发现?
参考回答

定时脚本读证书的到期时间,比如 tls.connect 之后 socket.getPeerCertificate().valid_to,剩 30 天就告警。证书用 Let's Encrypt 这类自动续期的话,也要监控续期任务有没有真的跑成功。

追问 4Node 服务要自己开 HTTPS,还是交给前面的 Nginx?
参考回答

一般交给 Nginx 或网关,证书集中管、续期方便,Node 只跑 HTTP。只有内网也要求加密、或者没有反向代理的时候,才让 Node 自己加载证书。

# 模块概览

30 秒速记

  • https 模块 API 和 http 几乎一一对应:https.get / https.request / https.createServer
  • 多出来的是 TLS 选项:服务端要 key、cert,客户端可以传 ca、rejectUnauthorized、servername
  • 浏览器和 Node 的信任库不一样:Node 用自带的 CA 列表,不读系统证书(Node 23.8 起才可以用 --use-system-ca)
  • 访问证书不受信任的站点,正确做法是加 ca,rejectUnauthorized: false 只能临时排查

https 模块的用法跟 http 几乎一样,把模块名和协议换掉就能跑,真正要多学的是证书。 服务端启动时要提供私钥和证书;客户端默认会严格校验对方证书,校验不过直接报错。早年 12306 用的是自己签的证书,浏览器要手动装根证书,Node 去请求也会报错,就是这个原因。还有一点容易忽略:Node 不用操作系统的证书库,公司内网 CA 装到系统里了,浏览器能打开,Node 照样报错。

这个模块的重要性,基本不用强调了。在网络安全问题日益严峻的今天,网站采用HTTPS是个必然的趋势。

在nodejs中,提供了 https 这个模块来完成 HTTPS 相关功能。从官方文档来看,跟 http 模块用法非常相似。

本文主要包含两部分:

  1. 通过客户端、服务端的例子,对https模块进行入门讲解。
  2. 如何访问安全证书不受信任的网站。(以 12306 为例子)

篇幅所限,本文无法对 HTTPS协议 及 相关技术体系 做过多讲解,有问题欢迎留言交流。

面试官追问

追问 1把 require('http') 换成 require('https'),服务就能上线了吗?
参考回答

不能。服务端 createServer 第一个参数要传 { key, cert },没有证书根本起不来。客户端那边,对方证书有问题也会直接报错,得先把证书链路理顺。

追问 2公司内网 CA 已经装进系统了,浏览器能打开,Node 还是报证书错误,为什么?
参考回答

Node 默认用自己打包的 CA 列表,不读系统证书库。启动时加 NODE_EXTRA_CA_CERTS=/path/company-ca.pem 就行,新版本也可以用 --use-system-ca。

追问 3联调时测试环境证书不受信任,想临时绕过,怎么做才不出事?
参考回答

只在这一个请求上传 ca 指向测试环境的证书,校验照常进行。实在要用 rejectUnauthorized: false,也只写在测试代码里,别用全局环境变量,更别带进生产配置。

追问 4一台服务器上挂了多个域名的 HTTPS 服务,客户端拿到的证书不对,可能是什么?
参考回答

SNI 没传对。Node 客户端默认用 hostname 当 servername,如果是用 IP 直连再手动加 Host 头,就要显式传 servername: 'api.example.com',服务端才知道该返回哪张证书。

# 客户端例子

30 秒速记

  • https.get(url, cb) 和 http.get 写法一样,回调拿到的 res 也是流
  • res.on('data') 里拿到的是一块块数据,要完整内容就拼起来等 end
  • .on('error') 管的是请求侧失败:DNS、连接、证书校验;正文读到一半断开要看 res 的 close / aborted
  • 证书错误会走这里的 error,比如 CERT_HAS_EXPIRED,不监听进程直接崩
  • 要设方法、请求头或写正文,就换 https.request

https.get() 跟 http.get() 的用法完全一样,只是请求地址换成了 https。 回调触发时只有状态码和响应头到了,正文通过 data 一块块来,示例里直接 process.stdout.write 边收边打。.on('error') 一定要写,HTTPS 比 HTTP 多了一类错误就是证书校验失败,过期、域名不匹配、自签名都会从这里抛出来。要自定义方法、请求头或者带正文,就换 https.request(options, cb),最后记得 end()。

跟http模块的用法非常像,只不过请求的地址是https协议的而已,代码如下:

var https = require('https');

https.get('https://www.baidu.com', function(res){
    console.log('status code: ' + res.statusCode);
    console.log('headers: ' + JSON.stringify(res.headers));

    res.on('data', function(data){
        process.stdout.write(data);
    });
}).on('error', function(err){
    console.error(err);
});
@前端进阶之旅: 代码已经复制到剪贴板

面试官追问

追问 1在 https.get 回调里直接读正文,只拿到一部分,为什么?
参考回答

回调触发时只有响应头到了,正文还在路上,会分多次 data 到达。要么边收边处理,要么累加后在 end 里用。

追问 2请求一个证书过期的站点,没写 .on('error'),会发生什么?
参考回答

进程直接崩,因为 error 事件没人监听会抛出来。监听了就能拿到 err.code === 'CERT_HAS_EXPIRED',按失败处理。

追问 3要带 Authorization 头发 POST,还能用 https.get 吗?
参考回答

不能,get 写死了 GET 还自动 end()。换成 https.request({ method: 'POST', headers: {...} }, cb),write 正文后 end()。

追问 4接口返回几百 MB 的文件,要把 data 拼成字符串再解析吗?
参考回答

不要,内存扛不住。直接 res.pipe(fs.createWriteStream('out.bin')),pipe 会自动处理背压,写盘慢了就暂停读取。

# 服务端例子

← 4.5 网络服务 http client4.7 网络TCP net →

fe